#include "Scene.h"
#include "Player.h"
#include "Factory.h"




// Scene::Scene(int width, int height, Player &p,2):shop(p),player(p),width(width), height(height)
// {   Point p1(width / 2,height / 2);
//     shop.Setpoint(p1);
//     Map.resize(height);
//     for (int i = 0; i < height; i++)
//     {
//         for (int j = 0; j < width; j++)
//         {
//             Map[i].push_back("🧱");
//         }
//     }
//     p.SetMaxWidth(width);
//     p.SetMaxHeight(height);

//     //先初始化容器 再初始化怪物
//     InitRandContainer();
//     InitialMonsters();
//     //初始化宝藏
//     InitTreasure();
// }
// Scene::Scene(int width, int height, Player &p,3):shop(p),player(p),width(width), height(height)
// {   Point p1(width / 2,height / 2);
//     shop.Setpoint(p1);
//     Map.resize(height);
//     for (int i = 0; i < height; i++)
//     {
//         for (int j = 0; j < width; j++)
//         {
//             Map[i].push_back("📊");
//         }
//     }
//     p.SetMaxWidth(width);
//     p.SetMaxHeight(height);

//     //先初始化容器 再初始化怪物
//     InitRandContainer();
//     InitialMonsters();
//     //初始化宝藏
//     InitTreasure();
// }
std::vector<Monster>* Scene1::getMonsters(){
    return &(this->Monsters);
}
std::vector<Monster>* Scene2::getMonsters(){
    return &(this->Monsters);
}
std::vector<Monster>* Scene3::getMonsters(){
    return &(this->Monsters);
}
std::vector<Treasure> *Scene1::getTreasures(){
    return &(this->Treasures);
}
std::vector<Treasure> *Scene2::getTreasures(){
    return &(this->Treasures);
}
std::vector<Treasure> *Scene3::getTreasures(){
    return &(this->Treasures);
}


void Scene1::show()
{
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            Map[i][j] =  "🌴";
        }
    }
    
    //角色
    Map[player.Getpoint().Gety()][player.Getpoint().Getx()] = player.GetSymbol();
    Map[shop.Getpoint().Gety()][shop.Getpoint().Getx()] = shop.GetSymbol();
    
    //怪
    for (auto m : Monsters)
    {
        if (m.GetHP() > 0)
        {
            Map[m.Getpoint().Gety()][m.Getpoint().Getx()] = m.GetSymbol();
            
        } 
    }

    //宝藏
    for (auto t : Treasures)
    {
     Map[t.Getpoint().Gety()][t.Getpoint().Getx()] = t.GetSymbol();
    }

    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            std::cout << Map[i][j] << " ";
        }
        std::cout<<std::endl;
    }
}
void Scene2::show()
{
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            Map[i][j] =  "🧱";
        }
    }
    
    //角色
    Map[player.Getpoint().Gety()][player.Getpoint().Getx()] = player.GetSymbol();
    Map[shop.Getpoint().Gety()][shop.Getpoint().Getx()] = shop.GetSymbol();
    
    //怪
    for (auto m : Monsters)
    {
        if (m.GetHP() > 0)
        {
            Map[m.Getpoint().Gety()][m.Getpoint().Getx()] = m.GetSymbol();
            
        } 
    }

    //宝藏
    for (auto t : Treasures)
    {
     Map[t.Getpoint().Gety()][t.Getpoint().Getx()] = t.GetSymbol();
    }

    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            std::cout << Map[i][j] << " ";
        }
        std::cout<<std::endl;
    }
}
void Scene3::show()
{
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            Map[i][j] =  "🧩";
        }
    }
    
    //角色
    Map[player.Getpoint().Gety()][player.Getpoint().Getx()] = player.GetSymbol();
    Map[shop.Getpoint().Gety()][shop.Getpoint().Getx()] = shop.GetSymbol();
    
    //怪
    for (auto m : Monsters)
    {
        if (m.GetHP() > 0)
        {
            Map[m.Getpoint().Gety()][m.Getpoint().Getx()] = m.GetSymbol();
            
        } 
    }

    //宝藏
    for (auto t : Treasures)
    {
     Map[t.Getpoint().Gety()][t.Getpoint().Getx()] = t.GetSymbol();
    }

    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            std::cout << Map[i][j] << " ";
        }
        std::cout<<std::endl;
    }
}

//判断是否在同一位置 (指针 异常 optional C++17)
Monster* Scene1::IsInSamePlace()
{
    //遍历整个怪兽容器
    for (auto&m : Monsters)
    {
        //判断位置 是否相等
        if (m.GetHP() > 0 && player.Getpoint().Getx() == m.Getpoint().Getx() && player.Getpoint().Gety() == m.Getpoint().Gety())
        {
            return &m;
        }
    }

    return nullptr;
}
Monster* Scene2::IsInSamePlace()
{
    //遍历整个怪兽容器
    for (auto&m : Monsters)
    {
        //判断位置 是否相等
        if (m.GetHP() > 0 && player.Getpoint().Getx() == m.Getpoint().Getx() && player.Getpoint().Gety() == m.Getpoint().Gety())
        {
            return &m;
        }
    }

    return nullptr;
}
Monster* Scene3::IsInSamePlace()
{
    //遍历整个怪兽容器
    for (auto&m : Monsters)
    {
        //判断位置 是否相等
        if (m.GetHP() > 0 && player.Getpoint().Getx() == m.Getpoint().Getx() && player.Getpoint().Gety() == m.Getpoint().Gety())
        {
            return &m;
        }
    }

    return nullptr;
}

//判断进入商店
void Scene1::BuyInShop()
{
    if (player.Getpoint().Getx() == shop.Getpoint().Getx() && player.Getpoint().Gety() == shop.Getpoint().Gety())
    {
        shop.show();
    }
}
//判断进入商店
void Scene2::BuyInShop()
{
    if (player.Getpoint().Getx() == shop.Getpoint().Getx() && player.Getpoint().Gety() == shop.Getpoint().Gety())
    {
        shop.show();
    }
}
//判断进入商店
void Scene3::BuyInShop()
{
    if (player.Getpoint().Getx() == shop.Getpoint().Getx() && player.Getpoint().Gety() == shop.Getpoint().Gety())
    {
        shop.show();
    }
}
//初始化怪兽
void Scene1::InitialMonsters()
{   
srand(time(nullptr));
MonsterFactory monsterFactory;
Monsters.push_back(monsterFactory.getMonster("虾兵",GetRandomPlace()));
Monsters.push_back(monsterFactory.getMonster("虾兵",GetRandomPlace()));
Monsters.push_back(monsterFactory.getMonster("虾兵",GetRandomPlace()));
Monsters.push_back(monsterFactory.getMonster("蟹将",GetRandomPlace()));
Monsters.push_back(monsterFactory.getMonster("蟹将",GetRandomPlace()));
Monsters.push_back(monsterFactory.getMonster("蟹将",GetRandomPlace()));
Monsters.push_back(monsterFactory.getMonster("龙",GetRandomPlace()));
Monsters.push_back(monsterFactory.getMonster("龙",GetRandomPlace()));
Monsters.push_back(monsterFactory.getMonster("龙",GetRandomPlace()));


}
void Scene2::InitialMonsters()
{   
srand(time(nullptr));
MonsterFactory monsterFactory;
Monsters.push_back(monsterFactory.getMonster("青蛙",GetRandomPlace()));
Monsters.push_back(monsterFactory.getMonster("青蛙",GetRandomPlace()));
Monsters.push_back(monsterFactory.getMonster("青蛙",GetRandomPlace()));
Monsters.push_back(monsterFactory.getMonster("小恶魔",GetRandomPlace()));
Monsters.push_back(monsterFactory.getMonster("小恶魔",GetRandomPlace()));
Monsters.push_back(monsterFactory.getMonster("小恶魔",GetRandomPlace()));
Monsters.push_back(monsterFactory.getMonster("小恐龙",GetRandomPlace()));
Monsters.push_back(monsterFactory.getMonster("小恐龙",GetRandomPlace()));
Monsters.push_back(monsterFactory.getMonster("小恐龙",GetRandomPlace()));


}
void Scene3::InitialMonsters()
{   
srand(time(nullptr));
MonsterFactory monsterFactory;
Monsters.push_back(monsterFactory.getMonster("小boss",GetRandomPlace()));
Monsters.push_back(monsterFactory.getMonster("大boss",GetRandomPlace()));

}

//初始化随机容器(洗牌)
void Scene1::InitRandContainer()
{
    //塞除角色坐标外的 所有坐标
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            //排除角色位置
            if (player.Getpoint().Getx() == j  && player.Getpoint().Gety() == i)
            {
                continue;
            }
            //排除商店位置
            if (i == height / 2 && j == width / 2)
            {
                continue;
            }
            RandPlaces.push_back(Point(j, i));
        }
    }
    //塞除角色坐标外的 所有坐标 在进行打乱 坐标不重复
    srand(time(nullptr));
    std::random_shuffle(RandPlaces.begin(), RandPlaces.end());
}
//初始化随机容器(洗牌)
void Scene2::InitRandContainer()
{
    //塞除角色坐标外的 所有坐标
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            //排除角色位置
            if (player.Getpoint().Getx() == j  && player.Getpoint().Gety() == i)
            {
                continue;
            }
            //排除商店位置
            if (i == height / 2 && j == width / 2)
            {
                continue;
            }
            RandPlaces.push_back(Point(j, i));
        }
    }
    //塞除角色坐标外的 所有坐标 在进行打乱 坐标不重复
    srand(time(nullptr));
    std::random_shuffle(RandPlaces.begin(), RandPlaces.end());
}
//初始化随机容器(洗牌)
void Scene3::InitRandContainer()
{
    //塞除角色坐标外的 所有坐标
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            //排除角色位置
            if (player.Getpoint().Getx() == j  && player.Getpoint().Gety() == i)
            {
                continue;
            }
            //排除商店位置
            if (i == height / 2 && j == width / 2)
            {
                continue;
            }
            RandPlaces.push_back(Point(j, i));
        }
    }
    //塞除角色坐标外的 所有坐标 在进行打乱 坐标不重复
    srand(time(nullptr));
    std::random_shuffle(RandPlaces.begin(), RandPlaces.end());
}

Point Scene1::GetRandomPlace()
{
    //从末尾开始拿 拿最后一个
    Point p = *(RandPlaces.end() - 1);
    RandPlaces.pop_back();
    return p;
}
Point Scene2::GetRandomPlace()
{
    //从末尾开始拿 拿最后一个
    Point p = *(RandPlaces.end() - 1);
    RandPlaces.pop_back();
    return p;
}
Point Scene3::GetRandomPlace()
{
    //从末尾开始拿 拿最后一个
    Point p = *(RandPlaces.end() - 1);
    RandPlaces.pop_back();
    return p;
}

//初始化宝藏
void Scene1::InitTreasure()
{      
    Treasure t1(GetRandomPlace());
    Treasure t2(GetRandomPlace());
    Treasure t3(GetRandomPlace());
    Treasure t4(GetRandomPlace());
    Treasures.push_back(t1); 
    Treasures.push_back(t2);
    Treasures.push_back(t3);
    Treasures.push_back(t4);
}
void Scene2::InitTreasure()
{      
    Treasure t1(GetRandomPlace());
    Treasure t2(GetRandomPlace());
    Treasure t3(GetRandomPlace());
    Treasure t4(GetRandomPlace());
    Treasures.push_back(t1); 
    Treasures.push_back(t2);
    Treasures.push_back(t3);
    Treasures.push_back(t4);
}
void Scene3::InitTreasure()
{      
    Treasure t1(GetRandomPlace());
    Treasure t2(GetRandomPlace());
    Treasure t3(GetRandomPlace());
    Treasure t4(GetRandomPlace());
    Treasures.push_back(t1); 
    Treasures.push_back(t2);
    Treasures.push_back(t3);
    Treasures.push_back(t4);
}

//进入战斗
void Battle(Player &p, Monster &m)
{   
    Dodge d1(m.GetdodgeChance());
    Crit c1(p.GetcritChance());
    Dodge d2(p.GetdodgeChance());
    Crit c2(m.GetcritChance());
    while (1)
    {
        BattleInterFace(p, m);
        sleep(1);
        if(d1.isDodged())
        {
            std::cout<<m.GetName()<<"|闪避！"<<std::endl;
            sleep(1);
            
        }
        else
        {
        int PlayerAttack=0;
        if(c1.isCriticalHit())
        {
        int Attack=p.GetAttack()*1.5;
        PlayerAttack = std::max(Attack - m.GetDefind(), 0);
        std::cout<<p.GetName()<<"|暴击！"<<std::endl;
        sleep(1);
        }
        else 
             PlayerAttack = std::max(p.GetAttack() - m.GetDefind(), 0);
        
        m.SetHP(m.GetHP() - PlayerAttack);
        std::cout << p.GetName() << "对" << m.GetName() << "造成了 " << PlayerAttack << "点伤害" << std::endl;
        sleep(1);
        if (m.GetHP() <= 0)
        {
            m.SetHP(0);
            BattleInterFace(p, m);
            std::cout << "你战胜了" << m.GetName() << "\n";
            std::cout << "获取经验值 " << m.GetExp() << " 和金钱 " << m.GetGloden() << " " << std::endl;
            sleep(1);

            p.SetExp(p.GetExp() + m.GetExp());
            p.LevelUp();

            p.SetGloden(m.GetGloden() + p.GetGloden());
            sleep(1);
            return;
        }
        }

        if(d2.isDodged())
        {
            std::cout<<p.GetName()<<"|闪避！"<<std::endl;
            sleep(1);
        }
        else
        {
        int MonsterAttack=0;
        if(c2.isCriticalHit())
        {
        int Attack=m.GetAttack()*1.5;
        MonsterAttack = std::max(Attack - p.GetDefind(), 0);
        std::cout<<m.GetName()<<"|暴击！"<<std::endl;
        sleep(1);
        }
        else 
            MonsterAttack = std::max(m.GetAttack() - p.GetDefind(), 0);
        p.SetHP(p.GetHP() - MonsterAttack);
        std::cout << m.GetName() << "对" << p.GetName() << "造成了 " << MonsterAttack << "点伤害" << std::endl;
        sleep(1);
        if (p.GetHP() <= 0)
        {
            std::cout << "你失败了!游戏结束!" << "\n";
            sleep(1);
            exit(-1);
        }
        }
    }
}

void BattleInterFace(Player& p, Monster& m)
{
    system("clear");
    std::cout<< "玩家名称: " << p.GetName() << "    VS    ";
    std::cout<< "怪兽名称: " << m.GetName() <<std::endl;
    
    std::cout<< "血量❤ : " << p.GetHP() << "       ";
    std::cout<< "血量❤ : " << m.GetHP() << std::endl;

    std::cout<< "攻击力⚔️ : " << p.GetAttack() << "     ";
    std::cout<< "攻击力⚔️ : " << m.GetAttack() << std::endl;

    std::cout<< "防御力🛡 : " << p.GetDefind() << "     ";
    std::cout<< "防御力🛡 : " << m.GetDefind() << std::endl;

}
//判断是否找到宝藏
void Scene1::FindTreasure(){
    int randomNum = rand() % 100 + 1;
    for (auto it = Treasures.begin(); it != Treasures.end(); ) {
    if (player.Getpoint().Getx() == it->Getpoint().Getx() && player.Getpoint().Gety() == it->Getpoint().Gety()) {
    if(randomNum<20){
          int coin=40;
          std::cout<<"获得"<<coin<<"个金币"<<std::endl; 
          player.SetGloden(player.GetGloden()+coin);   
          std::cout<<"任意键继续"<<std::endl; 
          getchar();  
    }else if(randomNum<80){
        auto a=std::make_shared<Diamond>("钻石",32,"钻石");
        Diamond d=*a;
        std::cout<<"获得"<<d.GetName()<<std::endl; 
        player.InsertBag(a);
        std::cout<<"任意键继续"<<std::endl; 
        getchar();
    }else{
        std::cout<<"遇见怪兽"<<std::endl; 
        std::cout<<"任意键继续"<<std::endl; 
        getchar();  
        Point p;
        p.Setx(player.Getpoint().Getx());
        p.Sety(player.Getpoint().Gety());
        blame1 *m = new blame1(p);
        Battle(player, *m);
    }

    it = Treasures.erase(it); // 删除并返回下一个迭代器
    return;
    } else {
    ++it; // 仅在没有删除时才递增迭代器
    }
}
}
//判断是否找到宝藏
void Scene2::FindTreasure(){
    int randomNum = rand() % 100 + 1;
    for (auto it = Treasures.begin(); it != Treasures.end(); ) {
    if (player.Getpoint().Getx() == it->Getpoint().Getx() && player.Getpoint().Gety() == it->Getpoint().Gety()) {
    if(randomNum<20){
          int coin=40;
          std::cout<<"获得"<<coin<<"个金币"<<std::endl; 
          player.SetGloden(player.GetGloden()+coin);   
          std::cout<<"任意键继续"<<std::endl; 
          getchar();  
    }else if(randomNum<80){
        auto a=std::make_shared<Diamond>("钻石",32,"钻石");
        Diamond d=*a;
        std::cout<<"获得"<<d.GetName()<<std::endl; 
        player.InsertBag(a);
        std::cout<<"任意键继续"<<std::endl; 
        getchar();
    }else{
        std::cout<<"遇见怪兽"<<std::endl; 
        std::cout<<"任意键继续"<<std::endl; 
        getchar();  
        Point p;
        p.Setx(player.Getpoint().Getx());
        p.Sety(player.Getpoint().Gety());
        blame1 *m = new blame1(p);
        Battle(player, *m);
    }

    it = Treasures.erase(it); // 删除并返回下一个迭代器
    return;
    } else {
    ++it; // 仅在没有删除时才递增迭代器
    }
}
}
//判断是否找到宝藏
void Scene3::FindTreasure(){
    int randomNum = rand() % 100 + 1;
    for (auto it = Treasures.begin(); it != Treasures.end(); ) {
    if (player.Getpoint().Getx() == it->Getpoint().Getx() && player.Getpoint().Gety() == it->Getpoint().Gety()) {
    if(randomNum<20){
          int coin=40;
          std::cout<<"获得"<<coin<<"个金币"<<std::endl; 
          player.SetGloden(player.GetGloden()+coin);   
          std::cout<<"任意键继续"<<std::endl; 
          getchar();  
    }else if(randomNum<80){
        auto a=std::make_shared<Diamond>("钻石",32,"钻石");
        Diamond d=*a;
        std::cout<<"获得"<<d.GetName()<<std::endl; 
        player.InsertBag(a);
        std::cout<<"任意键继续"<<std::endl; 
        getchar();
    }else{
        std::cout<<"遇见怪兽"<<std::endl; 
        std::cout<<"任意键继续"<<std::endl; 
        getchar();  
        Point p;
        p.Setx(player.Getpoint().Getx());
        p.Sety(player.Getpoint().Gety());
        blame1 *m = new blame1(p);
        Battle(player, *m);
    }

    it = Treasures.erase(it); // 删除并返回下一个迭代器
    return;
    } else {
    ++it; // 仅在没有删除时才递增迭代器
    }
}
}
// 复制赋值操作符实现
Scene1& Scene1::operator=(const Scene& other) {
    if (this == &other) {
        return *this; // 自我赋值检查
    }

    // 清理当前对象的资源（如果有动态分配的资源）
    // 不需要清理，因为这些数据是被拷贝的标准容器
    // 例如：Map.clear(); 等
    // 复制其他数据成员
    Map = other.Map;
    width = other.width;
    height = other.height;
    Monsters = other.Monsters;
    RandPlaces = other.RandPlaces;
    Treasures = other.Treasures;
    shop = other.shop;
    treasure = other.treasure;

    // 注意：引用成员不能复制
    // player = other.player; // 错误：引用成员不能被赋值

    return *this;
}

Scene2& Scene2::operator=(const Scene& other) {
    if (this == &other) {
        return *this; // 自我赋值检查
    }

    // 清理当前对象的资源（如果有动态分配的资源）
    // 不需要清理，因为这些数据是被拷贝的标准容器
    // 例如：Map.clear(); 等
    // 复制其他数据成员
    Map = other.Map;
    width = other.width;
    height = other.height;
    Monsters = other.Monsters;
    RandPlaces = other.RandPlaces;
    Treasures = other.Treasures;
    shop = other.shop;
    treasure = other.treasure;

    // 注意：引用成员不能复制
    // player = other.player; // 错误：引用成员不能被赋值

    return *this;
}
Scene3& Scene3::operator=(const Scene& other) {
    if (this == &other) {
        return *this; // 自我赋值检查
    }

    // 清理当前对象的资源（如果有动态分配的资源）
    // 不需要清理，因为这些数据是被拷贝的标准容器
    // 例如：Map.clear(); 等
    // 复制其他数据成员
    Map = other.Map;
    width = other.width;
    height = other.height;
    Monsters = other.Monsters;
    RandPlaces = other.RandPlaces;
    Treasures = other.Treasures;
    shop = other.shop;
    treasure = other.treasure;

    // 注意：引用成员不能复制
    // player = other.player; // 错误：引用成员不能被赋值

    return *this;
}

Scene2::Scene2(int width, int height, Player &p):Scene(width,  height,  p)
{   Point p1(width / 2,height / 2);
    shop.Setpoint(p1);
    Map.resize(height);
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            Map[i].push_back("🧱");
        }
    }
    p.SetMaxWidth(width);
    p.SetMaxHeight(height);

    //先初始化容器 再初始化怪物
    InitRandContainer();
    InitialMonsters();
    //初始化宝藏
    InitTreasure();
}

Scene3::Scene3(int width, int height, Player &p):Scene( width,  height, p)
{   Point p1(width / 2,height / 2);
    shop.Setpoint(p1);
    Map.resize(height);
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            Map[i].push_back("🧩");
        }
    }
    p.SetMaxWidth(width);
    p.SetMaxHeight(height);

    //先初始化容器 再初始化怪物
    InitRandContainer();
    InitialMonsters();
    //初始化宝藏
    InitTreasure();
}

Scene1::Scene1(int width, int height, Player &p):Scene( width,  height,p)
{   Point p1(width / 2,height / 2);
    shop.Setpoint(p1);
    Map.resize(height);
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            Map[i].push_back("🌴");
        }
    }
    p.SetMaxWidth(width);
    p.SetMaxHeight(height);

    //先初始化容器 再初始化怪物
    InitRandContainer();
    InitialMonsters();
    //初始化宝藏
    InitTreasure();
}

Scene::Scene(int width, int height, Player &p):shop(p),player(p),width(width), height(height)
{
}
